package com.gpj.netty.demo.base;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

/**
 * @className NettyServer
 * @description TODO
 * @author GPJ
 * @date 2021/2/24 9:38
 * @version 1.0
 **/
@Slf4j
public class NettyServer {
	public static void main(String[] args) throws InterruptedException {
		NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
		NioEventLoopGroup workGroup = new NioEventLoopGroup(2);

		try {
			// 创建服务器端的启动对象
			ServerBootstrap bootstrap = new ServerBootstrap();
			bootstrap.group(bossGroup, workGroup)
					// 使用NioServerSocketChannel作为服务器的通道实现
					.channel(NioServerSocketChannel.class)
					// 设置等待队列大小
					// 服务端处理【客户端连接】请求是顺序处理的,所以同一时间只能处理一个客户端连接
					.option(ChannelOption.SO_BACKLOG, 10)
					.childHandler(new ChannelInitializer<SocketChannel>() {
						@Override
						protected void initChannel(SocketChannel socketChannel) {
							//对workerGroup的SocketChannel设置处理器
							socketChannel.pipeline().addLast(new ServerHandler());
						}
					});
			log.info("netty server started...");
			// 绑定一个端口并且同步, 生成了一个ChannelFuture异步对象，通过isDone()等方法可以判断异步事件的执行情况
			// 启动服务器(并绑定端口)，bind是异步操作，sync方法是等待异步操作执行完毕
			ChannelFuture future = bootstrap.bind(9000).sync();

			// 给cf注册监听器，监听我们关心的事件(可选)
			/*ChannelFuture future = bootstrap.bind(9000);
			future.addListener(cf -> {
				if (cf.isSuccess()) {
					System.out.println("监听端口成功");
				} else {
					System.out.println("监听端口失败");
				}
			});
			future.sync();*/

			// 等待服务端监听端口关闭，closeFuture是异步操作
			// 通过sync方法同步等待通道关闭处理完毕，这里会阻塞等待通道关闭完成，内部调用的是Object的wait()方法
			future.channel().closeFuture().sync();
		}finally {
			bossGroup.shutdownGracefully();
			workGroup.shutdownGracefully();
		}
	}
}
